package com.hospital.common.core.function;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hospital.common.core.exception.ExceptionHelp;
import com.hospital.common.core.exception.ExceptionHelpEnum;
import com.hospital.common.core.module.controller.dto.BillDto;
import com.hospital.common.core.module.entity.BaseRequest;
import com.hospital.common.core.module.entity.Hl7MessageRequest;
import com.hospital.common.core.result.ErrorTip;
import com.hospital.common.core.result.SuccessTip;
import com.hospital.common.core.result.Tip;
import com.hospital.common.core.utils.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author lvyao
 * @description 推送消息等
 * @date 2022/1/15
 */
@Service
@Slf4j
public class PushMessage<T extends BaseRequest> {

    @Async
    public void sendLabBillInfo(String event, String hospitalCode, String hospitalName, String xmlHl7Url, String filePath, String postHl7Url, String status) {
        try {
            String readText = null;
            File file = new File(filePath);
            if (!file.exists()) {
                log.error(filePath + ":该文件不存在！");
                return;
            }
            try {
                InputStream in = new FileInputStream(file);
                SAXReader saxReader = new SAXReader();
                Document document = saxReader.read(in);
                Element rootElement = document.getRootElement();
                Element oml_o211 = rootElement.element(event);
                //检验计费申请推送
                if (status.equals("1")) {
                    //因检验系统处理逻辑问题申请单的计费标识暂不修改
                    List orc = oml_o211.elements("ORC");
                    for (Iterator<?> it = orc.iterator(); it.hasNext(); ) {
                        Element e = (Element) it.next();
                        e.element("ORC_1").setText("OH");
                        e.element("ORC_5").setText("IP");
                    }
//                    List obr = oml_o211.elements("OBR");
//                    for (Iterator<?> it = obr.iterator(); it.hasNext(); ) {
//                        Element e = (Element) it.next();
//                        e.element("OBR_5").setText("1");
//                    }
                    //撤销检验申请
                } else if (status.equals("2")) {
                    List orc = oml_o211.elements("ORC");
                    for (Iterator<?> it = orc.iterator(); it.hasNext(); ) {
                        Element e = (Element) it.next();
                        e.element("ORC_1").setText("OC");
                        e.element("ORC_5").setText("CA");
                    }
                }
                readText = document.asXML();
            } catch (Exception e) {
                log.error(filePath + ":读取该文件失败！");
            }
            boolean string2File = XMLUtil.string2File(readText, filePath);
            if (!string2File) {
                log.error("文件替换计费标记后：" + readText);
            }
            //文件转HL7消息接口调用 D:\7Edit 2.x\samples\xml\20121225.xml
            Hl7MessageRequest hl7MessageRequest = new Hl7MessageRequest();
            hl7MessageRequest.setFilename(filePath);
            hl7MessageRequest.setUrl(postHl7Url);
            hl7MessageRequest.setHospitalCode(hospitalCode);
            hl7MessageRequest.setHospitalName(hospitalName);
            String bodyStr = JSON.toJSONString(hl7MessageRequest);
            HttpResponse execute = HttpRequest.post(xmlHl7Url).body(bodyStr).execute();
            if (execute.getStatus() != 200) {
                ExceptionHelp exceptionHelp = new ExceptionHelp(ExceptionHelpEnum.HL7_API_POST_FILDS);
                log.error(filePath + "计费推送失败!" + exceptionHelp);
            }
            //推送成功后删除文件 不删除为计费申请以及撤销留存文件
//            FileUtils.delete(filePath);
            JSONObject jsonObject = JSONObject.parseObject(execute.body());
            String data = jsonObject.getString("data");
            log.info(filePath + "====hl7计费状态、撤销状态转换消息：" + data);
        } catch (Exception e) {
            log.error(e.toString() + "====================请求参数：" + filePath);
        }
    }

    @Async
    public void sendLabApplyInfo(String hospitalCode, String hospitalName, String xmlHl7Url, String filePath, String postHl7Url, String type) throws ExceptionHelp {
        //文件转HL7消息接口调用 D:\7Edit 2.x\samples\xml\20121225.xml
        Hl7MessageRequest hl7MessageRequest = new Hl7MessageRequest();
        hl7MessageRequest.setFilename(filePath);
        hl7MessageRequest.setUrl(postHl7Url);
        hl7MessageRequest.setHospitalCode(hospitalCode);
        hl7MessageRequest.setHospitalName(hospitalName);
        hl7MessageRequest.setType(type);
        String bodyStr = JSON.toJSONString(hl7MessageRequest);
        HttpResponse execute = HttpRequest.post(xmlHl7Url).body(bodyStr).execute();
        if (execute.getStatus() != 200) {
            ExceptionHelp exceptionHelp = new ExceptionHelp(ExceptionHelpEnum.HL7_API_POST_FILDS);
            log.error(filePath + "开单申请推送失败!" + exceptionHelp);
            throw exceptionHelp;
        }
        JSONObject jsonObject = JSONObject.parseObject(execute.body());
        String data = jsonObject.getString("data");
        log.info(filePath + "=====hl7开单申请转换消息：" + data);
    }

    public boolean sendBillMsg(String jsonString, String url) throws ExceptionHelp {
        //计费接口调用
//        String jsonString = JSON.toJSONString(billDto);
        HttpResponse execute = null;
        int status = 0;
        try {
            execute = HttpRequest.post(url).body(jsonString).execute();
            status = execute.getStatus();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ExceptionHelp(ExceptionHelpEnum.API_BILL_FILED);
        }
        if (status != 200) {
            if (status == 304) {
                throw new ExceptionHelp(ExceptionHelpEnum.INSERT_BILL_TABLE_FALID);
            } else if (status == 303) {
                throw new ExceptionHelp(ExceptionHelpEnum.NOT_ENOUGHT_BILL);
            }
            throw new ExceptionHelp(ExceptionHelpEnum.INSERT_BILL_FALID);
        }
        return true;
    }

    /**
     * rocketmq消息推送
     */
    @Async
    public ExceptionHelp sendMessage(T msg, String topic, String group) throws ExceptionHelp {

        return null;
    }
    public Tip sendRefundBillMsg(String refundBillVo, String url, RestTemplate restTemplate) {
        //计费接口调用
        Tip tip = new SuccessTip(null);
        try {
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, refundBillVo, JSONObject.class);
            //将网络连接异常的放入时间轮任务执行 start
            if (response.getStatusCode() != HttpStatus.OK) {
                setSendMessageSchdule(refundBillVo, url);
            }
            //将网络连接异常的放入时间轮任务执行 stop
            JSONObject jsonObject = response.getBody();
            if (!jsonObject.getString("infcode").equals("0")) {
                throw new RuntimeException(jsonObject.toJSONString());
            }
            tip.setData(jsonObject);
        } catch (RuntimeException e1) {
            tip = new ErrorTip(203, e1.getMessage());
        } catch (Exception e) {
            tip = new ErrorTip(204, e.getMessage());
        }
        return tip;
    }

    /**
     * 给执行失败的消息加入时间轮任务执行
     *
     * @param params
     */
    public void setSendMessageSchdule(String params, String url) {
//        AddSendTask addSendTask = new AddSendTask();
//        addSendTask.setUrl(url);
//        addSendTask.setCode("0000");
//        addSendTask.setData(params);
//        addSendTask.setRetries(2);
//        addSendTask.setTick(1);
//        addSendTask.setUnit(TimeUnit.MINUTES);
//        addTaskFunc.addTask(addSendTask);
    }


    public Tip pushAlipayMsg(String params, String url, RestTemplate restTemplate) {
        Tip tip = new SuccessTip(null);
        try {
            //直接调用医保时的入参设置及返回解析 start
//            //设置请求头
            HttpHeaders httpHeaders = new HttpHeaders();
            //传递请求体时必须设置传递参数的格式，为Content-Type ： application/json
            httpHeaders.add("Content-Type", "application/json;charset=UTF-8");
            // 2.请求头 & 请求体
            HttpEntity<JSON> fromEntity = new HttpEntity(params, httpHeaders);
//            String startTime = DateUtil.getAllTime();
//            StopWatch stopwatch2 = new StopWatch();
//            stopwatch2.start();
            JSONObject response = restTemplate.postForObject(url, fromEntity, JSONObject.class);
//            stopwatch2.stop();
//            String endTime = DateUtil.getAllTime();
//            log.info("耗时：" + String.valueOf(stopwatch2.getTotalTimeSeconds()));
            //直接调用医保时的入参设置及返回解析  stop
//            //调用平台的方式  start
//            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, params, String.class);
            //微信移动医保请求成功且业务处理成功才解析返回，以及嵌入式医保三个接口返回0000才处理
            if ("0000".equals(response.getString("code"))) {
//                JSONObject response = JSON.parseObject(responseEntity.getBody());
                //调用平台的方式  stop
//                JSONObject convertValue = JSON.parseObject(Sm2Demo.denc(response.toJSONString()));
                JSONObject convertValue = JSON.parseObject(response.toJSONString());
                tip.setData(convertValue);
            } else {
                tip = new ErrorTip(304, response.toJSONString());
            }
        } catch (Exception e) {
            tip = new ErrorTip(303, e.getMessage());
        }
        return tip;
    }
}
